#pragma once
#include <cstdio>
#include <string>
#include <ctime>

namespace liang
{
#define DEBUG_LEVEL 0
#define INFO_LEVEL 1
#define ERROR_LEVEL 2
#define DEFAULT_LEVEL DEBUG_LEVEL

#define LOG(level, fmt, ...) do {                            \
    if (level >= DEFAULT_LEVEL) {                            \
        time_t t = time(nullptr);                            \
        struct tm *tm = localtime(&t);                       \
        char time_str[32];                                   \
        strftime(time_str, sizeof(time_str), "%H:%M:%S", tm);\
        std::string levelstr;                                \
        if (level == DEBUG_LEVEL) levelstr = "DEBUG";        \
        else if (level == INFO_LEVEL) levelstr = "INFO";     \
        else if (level == ERROR_LEVEL) levelstr = "ERROR";   \
        else levelstr = "UNKNOWN";                           \
        fprintf(stderr, "[%s][%s][%s:%d] " fmt "\n",         \
                levelstr.c_str(), time_str, __FILE__, __LINE__, ##__VA_ARGS__); \
    }                                                        \
} while(0)

#define DEBUG(fmt, ...) LOG(DEBUG_LEVEL, fmt, ##__VA_ARGS__)
#define INFO(fmt, ...) LOG(INFO_LEVEL, fmt, ##__VA_ARGS__)
#define ERROR(fmt, ...) LOG(ERROR_LEVEL, fmt, ##__VA_ARGS__)
}